package com.neusoft.ch7;

import com.neusoft.ch7.interfacedemo.Animal;
import com.neusoft.ch7.singletone.Singletone;
import com.neusoft.ch7.singletone.Singletone2;
import com.neusoft.ch7.singletone.Singletone3;
import com.neusoft.ch7.interfacedemo.*;

/*
 * 课堂笔记：
 *    1、interface关键字(弥补类的单继承的缺陷)
 *       接口：特殊的抽象类；
 *            接口中只有抽象方法，没有属性；
 *            命名规范：类的命名规范之前+I的，例如：IShape；IMovable
 *       解析：
 *           接口中所有的方法都是抽象方法；其中修饰符  public abstract 都可以全部或部分省略；
 *           接口不可以有带方法体的方法；（新特性中，可以使用default定义带方法体的方法）
 *           接口中定义的变量都是public类型的静态常量；其中修饰符  public  static final 可以全部或部分省略；
 * 		            接口没有构造方法；
 *           接口不能被实例化，不能直接new；
 *           
 *           接口可以多继承；作用：弥补类的单继承的缺陷；
 *           接口多继承体现在以下两个方面：
 *           
 *           一：类继承接口：
 *           	如果子类实例化（继承）接口，需要使用关键字 implements，类的继承使用关键字 extends；
 *           		例如： 子类  implements 接口；
 *           	一个子类可以继承多个父接口；
 *           		例如：子类  implements 接口1，接口2，接口n;
 *              子类如果没有全部实现父接口的抽象方法，则该子类只能定义为抽象类；
 *               
 *           二：接口继承接口
 *              接口和接口之间可以进行多继承；使用关键字 extends；
 *                  例如：子接口  extends 父接口1，父接口2，父接口n;
 *           
 *       课下作业：
 *           接口和抽象类的异同点？    
 *       作用：
 *           软件工程的思想：面向接口的编程（面向父类的编程）
 *           接口和抽象类的使用原则：
 *              当OOP时，一个类进行抽象封装时，既有抽象方法、又有非抽象方法；或者该类有属性优先考虑使用抽象类；
 *              当OOP时，一个类进行抽象封装时，只有抽象方法，则优先使用接口；    
 *              
 *           接口封装的是一组行为能力（接口封装的十一组抽象方法），
 *           也就是说，如果一个类实现（继承）了一个接口表示该类具有某种能力；
 *    
 *    2、单件（单例）模式
 *       一个类有且仅有一个实例对象；每次获取的都是同一个实例对象；
 *       实现：
 *          (1) 声明一个单件类类型静态变量（静态属性）【目的：保证实例对象常驻内存】
 *          (2) 将构造方法私有化（用private修饰）【目的：外部类无法通过new创建该类的实例对象】
 *          (3) 提供一个静态方法，用于获取该单件模式类的实例对象【目的：绕开new方式获取该类的实例对象】    
 *             
 *       推荐参阅：https://www.cnblogs.com/Ycheng/p/7169381.html
 *    3、匿名内部类
 *      在一个类内部定义的类叫做内部；
 *      匿名内部类：可以在使用时创建抽象类或接口的实现之后的匿名子类的实例对象，并调用其行为方法。
 *      作用：事件处理、回调
 *      好处：调用方法的同时可以实现该方法；（实现抽象方法和调用抽象方法可以同时进行）
 *      语法：
 *          new 抽象类/接口(构造方法列表){
 *          	// 现场直接实现抽象类或接口没有实现的抽象方法
 *          }.行为方法();
 *      
 *      应用场景：当只关于行为方法的结果时，而不关注动作的发出者时，优先使用匿名内部类；
 *      
 *      
 *         
 */
public class TestCh7 {

	public static void main(String[] args) {
		test02();

	}
	
	/**
	 * 匿名内部类
	 */
	private static void test02() {
		// 普通类调用行为方法
		Animal an0 = new Animal();
		an0.speak();
		// 调用抽象类、接口的行为
		/*
		 * 1、因为抽象接口无法直接通过new创建；
		 * 2、匿名内部类通过在new的同时直接实现未实现抽象方法的方式创建该抽象类或接口的一个实现子类的实现对象；
		 *    2.1 创建了一个匿名子类，用于实现抽象类或接口的抽象方法；
		 *    2.2 创建这个匿名子类的实例对象
		 *    2.3 通过创建的这个匿名实例对象取调用刚才实现的行为方法；
		 */
		new ISpeakable() {
			@Override
			public void speak() {
				// 抽象行为的实现（此处进行业务逻辑处理）
				System.out.println("匿名内部类的好处就是在调用匿名内部类的行为方法时，同时可以实现该方法的业务逻辑");
			}
			}.speak();
			
			// 变形用法
			ISpeakable isk = new ISpeakable() {
				@Override
				public void speak() {
					// 抽象行为的实现（此处进行业务逻辑处理）
					System.out.println("匿名内部类的好处就是在调用匿名内部类的行为方法时，同时可以实现该方法的业务逻辑");
				}
				};
		 isk.speak();		
		 		
	}
	
	/**
	 * 单件模式类示例
	 */
	private static void test01() {
		int i = 2;
		int j = 2;
		System.out.println("i==j:" + (i == j));
		// 普通类每次通过new创建出来的实例对象，都不是同一个，而是多个
		Animal an0 = new Animal();
		Animal an1 = new Animal();
		// == 运算符可以判定基本类型的值是否相同；还以判定引用类型（对象类型）是否是同一个实例对象
		System.out.println("an0==an1:" + (an0 == an1));

		// 单件模式
		System.out.println("==================");
		Singletone st0 = Singletone.getInstance();
		Singletone st1 = Singletone.getInstance();
		System.out.println("st0==st1:" + (st0 == st1));
		// 单件模式
		System.out.println("==================");
		Singletone2 st20 = Singletone2.getInstance();
		Singletone2 st21 = Singletone2.getInstance();
		System.out.println("st20==st21:" + (st20 == st21));
		// 单件模式
		System.out.println("==================");
		Singletone3 st30 = Singletone3.getInstance();
		Singletone3 st31 = Singletone3.getInstance();
		System.out.println("st30==st31:" + (st30 == st31));
	}

}
